COMMONSXML-7: SchemaFactory: capability-driven hardening - #13
Merged
garydgregory merged 3 commits intoJul 5, 2026
Merged
Conversation
Replace the per-implementation class-name dispatch for Schema with a single wrapper-based recipe, the same for every implementation. The hardening lives entirely in the existing HardeningSchemaFactory / HardeningSchema / HardeningValidator wrappers, so there is no per-implementation branching, no FEATURE_SECURE_PROCESSING and no limit configuration on the factory itself: - HardeningSchemaFactory installs a deny-all LSResourceResolver on the factory (blocking xs:import/include/redefine at compile time) and rewrites every newSchema(Source[]) through an XmlFactories-hardened reader. - HardeningSchema wraps every Validator/ValidatorHandler the inner Schema produces and re-installs the deny-all resolver on each (blocking xsi:schemaLocation at validation time), since neither the JDK nor Xerces reliably propagates it through Schema. - HardeningValidator rewrites the Source on every validate(Source) call. The hardened reader from XmlFactories.harden(Source) already carries FEATURE_SECURE_PROCESSING and the processing limits, so a DOCTYPE, external entity or Billion Laughs payload in the schema or instance document is bounded there rather than on this factory. The JAXP 1.5 ACCESS_EXTERNAL_* properties are deliberately not set: the deny-all resolver already blocks the same fetches on every implementation, and the JDK 8 SchemaFactory has a bug whereby those properties keep blocking even when a caller's own resolver would grant the access, so leaving them unset lets a caller re-enable specific lookups by swapping the resolver. The JDK block now surfaces as the resolver's SecurityException rather than a SAXException, which the attack-test assertions already accept. StockJdkProvider.configure(SchemaFactory), XercesProvider.configure(SchemaFactory) with its per-product hardeners, XmlFactories.dispatch(SchemaFactory) and Limits.applyToJdkSchema are removed; XmlFactories.newSchemaFactory() wraps in HardeningSchemaFactory directly. An implementation is no longer rejected for being unrecognized. Assisted-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Member
|
The Jira ticket is COMMONSXML-7 |
…e-based-hardening
Member
|
Hi @ppkarwasz |
…e-based-hardening
Member
Author
|
I merged it with |
Member
|
Thank you @ppkarwasz , merged 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Applies the COMMONSXML-1 capability-driven approach to the Schema path, replacing the per-implementation class-name dispatch for
SchemaFactorywith a single wrapper-based recipe shared by every implementation.HardeningSchemaFactoryinstalls a deny-allLSResourceResolveron the factory (compile-timexs:import/include/redefine) and rewrites everynewSchema(Source[])through anXmlFactories-hardened reader.HardeningSchemare-installs the resolver on eachValidator/ValidatorHandler(validate-timexsi:schemaLocation), andHardeningValidatorrewrites the Source on everyvalidate(Source).XmlFactories.harden(Source)already carries them, so DOCTYPE / external-entity / Billion Laughs payloads in the schema or instance document are bounded there.StockJdkProvider.configure(SchemaFactory),XercesProvider.configure(SchemaFactory)with its per-product hardeners,XmlFactories.dispatch(SchemaFactory)andLimits.applyToJdkSchemaare removed;XmlFactories.newSchemaFactory()wraps inHardeningSchemaFactorydirectly. No new class is introduced (net -84 lines).Behaviour: the JAXP 1.5
ACCESS_EXTERNAL_*properties are deliberately not set (the deny-all resolver covers the same fetches, and dropping them avoids the JDK 8 property-override bug, letting a caller re-enable specific lookups via their own resolver). The JDK block now surfaces asSecurityExceptionrather thanSAXException; the attack-test assertions already accept both. An unrecognized implementation is hardened rather than rejected. The schema-engine-internalmaxOccursnode limit is no longer pinned on the factory (not exercised by any test); document-parsing limits remain covered via the hardened reader.mvn verifygreen across the stock JDK and external Xerces profiles.